using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace DiceRollerModel
{
    public class Die
    {
        public const int Width = 67;
        internal float DistanceTraveled = 0f;
        public Vector2 Velocity { get; set; }
        public Rectangle Location { get; set; }
        public Rectangle TextureWindow { get; set; }
        public Texture2D Texture { get; set; }
        private static Random r = new Random();
        public void Roll()
        {
           
            double angle = r.NextDouble();
            angle *= 2 * Math.PI;
            double magnitude = r.Next(20, 30);

            //Test
           // angle = 0;

            Vector2 newVelocity = new Vector2((float)(magnitude * Math.Sin(angle)), (float)(magnitude * Math.Cos(angle)));
            Velocity = newVelocity;
            
        }

        public void UpdateLocation(Box viewScreen, List<Die> Dice)
        {
            Vector2 curVelocity = Velocity;
            if (curVelocity.Length() != 0)
            {
                Rectangle loc = Location;
                loc.X += (int)(curVelocity.X);
                loc.Y += (int)(curVelocity.Y);
                Location = loc;
                bool collided = true;
                while (collided)
                {
                    collided = false;
                    collided |= CheckBoundaries(ref loc, ref curVelocity, viewScreen);
                    collided |= CheckCollisions(ref loc, ref curVelocity, Dice);
                    Location = loc;
                }
                float curMagnitude = curVelocity.Length();
                DistanceTraveled += curMagnitude;
                DistanceTraveled %= (Width * 6);
                
                float newMagnitude = CalcNewMagnitude(curMagnitude);
                if (newMagnitude < 0)
                {
                    newMagnitude = 0;
                }
                float decreaseRatio = newMagnitude / curMagnitude;

                curVelocity.Y *= decreaseRatio;
                curVelocity.X *= decreaseRatio;
                Velocity = curVelocity;
            }
            else
            {
                if (DistanceTraveled % Width < Width/2)
                {
                    DistanceTraveled = DistanceTraveled % Width < 4 ? DistanceTraveled - DistanceTraveled % Width : DistanceTraveled - 4;
                }
                else
                {
                    DistanceTraveled = DistanceTraveled % Width > Width - 4 ? DistanceTraveled + (Width - DistanceTraveled % Width) : DistanceTraveled + 4;
                }

            }
            Rectangle Window = TextureWindow;
                Window.X = (int)DistanceTraveled;
               
                TextureWindow = Window;
        }

        private static float CalcNewMagnitude(float curMagnitude)
        {
            return curMagnitude > 5 ? curMagnitude - .5f : curMagnitude - .25f;
        }

        /*
         * Calculate new location based on collision intersection point
         * Update angle being traveled.
         */
        private bool CheckBoundaries(ref Rectangle loc, ref Vector2 curVelocity ,Box viewScreen)
        {
            bool ret = false;
            if (loc.Left < 0)
            {
                loc.X = Math.Abs(loc.X);
                curVelocity.X *= -1;
                ret = true;
            }
            else if (loc.Right > viewScreen.Width)
            {
                loc.X = viewScreen.Width - (loc.Right - viewScreen.Width) - loc.Width;
                curVelocity.X *= -1;
                ret = true;
            }
            else if (loc.Top < 0)
            {
                loc.Y = Math.Abs(loc.Y);
                curVelocity.Y *=-1;
                ret = true;
            }
            else if (loc.Bottom > viewScreen.Height)
            {
                loc.Y = viewScreen.Height - (loc.Bottom - viewScreen.Height) - loc.Height;
                curVelocity.Y *= -1;
                ret = true;
            }
            return ret;
        }

        private bool CheckCollisions( ref Rectangle loc, ref Vector2 curVelocity, List<Die> Dice)
        {
            bool ret = false;
            foreach (Die d in Dice)
            {
                if (d == this)
                {
                    Console.WriteLine("Hello");
                }
                else if(loc.Intersects(d.Location))
                {

                    Vector2 normalVector = GenerateNormal(loc, d.Location);
                    Vector2 result = new Vector2();

                    Vector2 cmv = (curVelocity + d.Velocity) / 2;

                    curVelocity -= cmv;
                    Vector2.Reflect(ref curVelocity, ref normalVector, out result);
                    Vector2 changeVelocity = result - curVelocity;
                    curVelocity += cmv;

                    Vector2 otherVeloctiy = d.Velocity - changeVelocity;
                    d.Velocity = otherVeloctiy;

                    curVelocity += changeVelocity;


                    //Rectangle intersection = Rectangle.Intersect(loc, d.Location);
                   // loc.X += intersection.Width * ((loc.X > d.Location.X) ? 1 : -1);
                   // loc.Y += intersection.Height * ((loc.Y > d.Location.Y) ? 1 : -1);


                }
                
            }
            return ret;
        }

        private Vector2 GenerateNormal(Rectangle loc, Rectangle rectangle)
        {
            Vector2 lineBetween = new Vector2 (rectangle.Center.X - loc.Center.X, rectangle.Center.Y - loc.Center.Y);
            lineBetween.Normalize();
            return lineBetween;
        }

    }
}
